<template>
  <div class="app-content" ref="containerRef" style="height: 800px"></div>
</template>

<script>
import { Graph, Node, Edge, Shape, Line, Path, Curve } from "@antv/x6";
import { register } from "@antv/x6-vue-shape";
import Hierarchy from "@antv/hierarchy";
import TreeNode from "./treeNode.vue";
import ContentNode from "./contentNode.vue";
import MethodNode from "./methodNode.vue";

export default {
  name: "ModelGraphChart",
  components: {},
  data() {
    return {
      graph: null,
      graphChart: null,
    };
  },
  mounted() {
    this.register();
  },
  methods: {
    register() {
      register({
        shape: "tree-node",
        width: 140,
        height: 40,
        component: {
          render: (h) =>
            h(TreeNode, {
              on: {
                expandChildren: (type, cnode) => {
                  this.updateData(type, cnode);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      register({
        shape: "target-node",
        width: 280,
        height: 136,
        component: {
          render: (h) =>
            h(ContentNode, {
              on: {
                expandChildren: (data, a) => {
                  console.log(data, a);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
            right: {
              position: "right",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      register({
        shape: "method-node",
        width: 140,
        height: 60,
        component: {
          render: (h) =>
            h(MethodNode, {
              on: {
                change: (data, a) => {
                  console.log(data, a);
                },
              },
            }),
        },
        ports: {
          groups: {
            left: {
              position: "left",
              attrs: {
                circle: {
                  display: "none",
                  r: 6,
                  magnet: true,
                  stroke: "#1f89cc",
                  strokeWidth: 2,
                  fill: "#fff",
                },
              },
            },
          },
        },
      });
      // 边
      Graph.registerEdge(
        "model-edge",
        {
          inherit: "edge",
          attrs: {
            line: {
              stroke: "#004892",
              strokeWidth: 1,
              targetMarker: {
                name: "classic",
              },
              // targetMarker: {
              //   tagName: "path",
              //   fill: "yellow", // 使用自定义填充色
              //   stroke: "green", // 使用自定义边框色
              //   strokeWidth: 2,
              //   d: "M 20 -10 0 0 20 10 Z",
              // },
            },
          },
          // connector: {
          //   name: "smooth",
          // },
          zIndex: 0,
        },
        true
      );

      Graph.registerConnector(
        "multi-smooth",
        (sourcePoint, targetPoint, routePoints, options) => {
          const { index = 0, total = 1, gap = 12 } = options;
          const line = new Line(sourcePoint, targetPoint);
          const centerIndex = (total - 1) / 2;
          const dist = index - centerIndex;
          const diff = Math.abs(dist);
          const factor = diff === 0 ? 1 : diff / dist;
          const vertice = line
            .pointAtLength(line.length() / 2 + gap * factor * Math.ceil(diff))
            .rotate(90, line.getCenter());

          const points = [sourcePoint, vertice, targetPoint];
          const curves = Curve.throughPoints(points);
          const path = new Path(curves);
          return options.raw ? path : path.serialize();
        },
        true
      );
    },
    init(data) {
      this.graphChart = data;
      const that = this;
      const containerRef = this.$refs.containerRef;
      const graph = new Graph({
        container: containerRef,
        autoResize: true,
        // interacting: {
        //   nodeMovable: false
        // }
        // connecting: {
        //   connectionPoint: "anchor",
        //   allowMulti:'withPort'
        // },
        // mousewheel: {
        //   enabled: true,
        //   minScale: 0.1,
        //   maxScale: 4,
        // },
        // panning: {
        //   enabled: true,
        // },
        // interacting: {
        //   nodeMovable: false,
        // },
        // keyboard: {
        //   enabled: true,
        // },
      });
      this.graph = graph;
      console.log("data", data);
      const render = () => {
        const result = Hierarchy.mindmap(data, {
          direction: "H",
          getHeight(d) {
            return d.height;
          },
          getWidth(d) {
            return d.width;
          },
          getHGap() {
            return 120;
          },
          getVGap() {
            return 110;
          },
          getSide: () => {
            return "right";
          },
        });
        console.log("result", result);

        const cells = [];
        const traverse = (hierarchyItem) => {
          if (hierarchyItem) {
            const { data, children, parent = null } = hierarchyItem;
            console.log(hierarchyItem);
            if (data.shape === "tree-node") {
              console.log("name", data.label);
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: data.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  // visible: data.id === 'none' ? false : parent.data.isActived,
                  visible: data.isShow,
                  ports: {
                    items: [
                      {
                        id: "port_left" + data.id,
                        group: "left",
                      },
                      {
                        id: "port_right" + data.id,
                        group: "right",
                      },
                    ],
                  },
                  data,
                })
              );
            } else if (data.shape === "target-node") {
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: data.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  // visible: parent.data.isActived,
                  visible: data.isShow,
                  ports: {
                    items: [
                      {
                        id: "port_left" + data.id,
                        group: "left",
                      },
                      {
                        id: "port_right" + data.id,
                        group: "right",
                      },
                    ],
                  },
                  data,
                })
              );
            } else if (data.shape === "method-node") {
              cells.push(
                graph.createNode({
                  id: data.id,
                  shape: data.shape,
                  x: data.x,
                  y: data.y,
                  width: data.width,
                  height: data.height,
                  label: data.label,
                  type: data.type,
                  // visible: parent.data.isActived,
                  visible: data.isShow,
                  ports: {
                    items: [
                      {
                        id: "port_left" + data.id,
                        group: "left",
                      },
                    ],
                  },
                  data,
                })
              );
            }
            console.log("children", children);
            if (children) {
              children.forEach((item, i) => {
                const { id, data: cdata } = item;
                console.log("item1", item);
                console.log("item2", data.id, id);
                console.log("item3", {
                  dataX: data.x,
                  dataY: data.y,
                  x: data.x + data.width + 10,
                  y: data.y,
                });
                cells.push(
                  graph.createEdge({
                    shape: "model-edge",
                    connector: {
                      // name: cdata.shape === "method-node" ? "normal" : "smooth", // smooth
                      // name: "multi-smooth",
                      // name: "rounded",
                      name: "normal",
                    },
                    source: {
                      cell: data.id,
                      port: "port_right" + data.id,
                      anchor: {
                        name: "right",
                        args: {
                          // offset: "center",
                        },
                      },
                      connectionPoint: "anchor",
                    },
                    target: {
                      cell: id,
                      port: "port_left" + id,
                      anchor: {
                        name: "left",
                        args: {
                          offset: "center",
                        },
                      },
                      connectionPoint: "anchor",
                    },
                    router: {
                      name: "manhattan",
                      // name: "orth",
                      // args: {
                      //   step: 10,
                      // },
                    },
                    // vertices: [
                    //   {
                    //     x: data.x + data.width + 10,
                    //     y: data.y + data.height / 2,
                    //   },
                    // ],

                    // router: {
                    //   name: "er",
                    //   args: {
                    //     offset: 40,
                    //   },
                    // },
                    // router: {
                    //   name: "er",
                    //   args: {
                    //     offset: 30,

                    //   },
                    // },

                    // router: {
                    //   name: "metro",
                    //   args: {
                    //     startDirections: ["bottom"],
                    //     endDirections: ["top"],
                    //   },
                    // },

                    // router: {
                    //   name: "orth",
                    //   args: {},
                    // },
                    // vertices: [
                    // { x: item.x - 10, y: item.y },
                    // ],
                    // attrs: {
                    //   symbol: {
                    //     atConnectionRatio: 0.75, // 沿边长度方向，距离起点 75% 位置处
                    //   },
                    //   arrowhead: {
                    //     atConnectionLength: 100, // 沿边长度方向，距离起点 100px 位置处
                    //   },
                    // },
                    // line: {
                    //   // sourceMarker: {
                    //   //   tagName: "path",
                    //   //   d: "M 20 -10 0 0 20 10 Z",
                    //   // },
                    //   targetMarker: {
                    //     tagName: "path",
                    //     fill: "yellow", // 使用自定义填充色
                    //     stroke: "green", // 使用自定义边框色
                    //     strokeWidth: 2,
                    //     d: "M 20 -10 0 0 20 10 Z",
                    //   },
                    // },
                    // },
                  })
                );

                traverse(item);
              });
            }
          }
        };
        traverse(result);
        graph.resetCells(cells);
        graph.positionContent("left");
      };
      // this.graph.render = render
      // 渲染
      render();
    },
    updateData(type, cnode) {
      // console.log(type, cnode)
      // const idArr = cnode.data.id.split('-')

      // const hide = (list) => {
      //   if (list && list.length) {
      //     list.forEach(item => {
      //       const cell = this.graph.getCellById(item.id)
      //       cell.data.isActived = false
      //       cell.visible = false
      //       if (item.children && item.children.length) {
      //         hide(item.children)
      //       }
      //     })
      //   }
      // }

      // const show = (list) => {
      //   if (list && list.length) {
      //     list.forEach(item => {
      //       const cell = this.graph.getCellById(item.id)
      //       cell.data.isActived = true
      //       cell.visible = true
      //     })
      //   }
      // }

      // if (type === 'expand') {
      //   show(cnode.data.children)
      // } else {
      //   hide(cnode.data.children)
      // }

      const idArr = cnode.data.id.split("-");
      const run = (pre) => {
        const succ = this.graph.getSuccessors(pre, { distance: 1 });
        console.log(succ);
        if (succ) {
          succ.forEach((node) => {
            node.visible = !node.visible;
            // content和method一起显示隐藏
            if (
              node.data.type === "content" &&
              node.data.children &&
              node.data.children.length
            ) {
              run(node);
            } else if (node.data.isActived) {
              run(node);
            }
          });
        }
      };
      const update = (list) => {
        if (list && list.length) {
          list.forEach((item) => {
            if (item.id !== cnode.data.id) {
              if (!cnode.data.id.includes(item.id)) {
                const cell = this.graph.getCellById(item.id);
                if (cell.data.isActived) {
                  cell.data.isActived = false;
                  run(cell);
                }
              }

              if (item.children && item.children.length) {
                update(item.children);
              }
            }
          });
        }
      };

      update(this.graphChart.children);

      // 展开
      if (type === "expand") {
        cnode.data.isActived = true;
        if (idArr[2]) {
          const cell1 = this.graph.getCellById(`${idArr[0]}-${idArr[1]}`);
          const cell2 = this.graph.getCellById(`${idArr[0]}`);
          cell1.data.isActived = true;
          cell2.data.isActived = true;
        } else if (idArr[1]) {
          const cell2 = this.graph.getCellById(`${idArr[0]}`);
          cell2.data.isActived = true;
        }
      } else {
        cnode.data.isActived = false;
      }

      run(cnode);
    },
  },
};
</script>

<style lang="scss" scoped></style>
